package com.niiwoo.civet.user.service.local;

import com.alibaba.fastjson.JSON;
import com.niiwoo.civet.trade.enums.LoanLimitMessageEnum;
import com.niiwoo.civet.user.dao.aggregation.UserRealNameInfo;
import com.niiwoo.civet.user.dao.entity.*;
import com.niiwoo.civet.user.dao.mapper.*;
import com.niiwoo.civet.user.dto.LinkManDubboInfoDTO;
import com.niiwoo.civet.user.dto.UserPersonalDubboInfoDTO;
import com.niiwoo.civet.user.dto.UserProfessionDubboInfoDTO;
import com.niiwoo.civet.user.dto.request.DripSummaryInfoDTO;
import com.niiwoo.civet.user.dto.response.LoanConsumeInfoResponseDTO;
import com.niiwoo.civet.user.dto.request.customsystem.QueryBorrowerUserRequestDTO;
import com.niiwoo.civet.user.dto.response.UserInfoCheckResposeDTO;
import com.niiwoo.civet.user.dto.response.UserRealNameInfoDTO;
import com.niiwoo.civet.user.dto.response.customsystem.QueryBorrowerUserResponseDTO;
import com.niiwoo.civet.user.enums.UserDataStatusEnum;
import com.niiwoo.civet.user.enums.UserDataTypeEnum;
import com.niiwoo.civet.user.enums.UserPersonalEnum;
import com.niiwoo.tripod.base.component.PrivacyMasks;
import com.niiwoo.tripod.base.utils.DateUtils;
import com.niiwoo.tripod.service.component.SnowflakeIdWorker;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * @Author: wuke
 * @Description:
 * @Date: Created in 16:00 2017/11/8
 */
@Slf4j
@Service
public class UserDataService {

    @Autowired
    private SnowflakeIdWorker snowflakeIdWorker;
    @Autowired
    private UserPersonalInfoMapperExt userPersonalInfoMapper;
    @Autowired
    private UserLinkmanInfoMapperExt userLinkmanInfoMapperExt;
    @Autowired
    private UserProfessionInfoMapperExt userProfessionInfoMapper;
    @Autowired
    private UserAreaDictionaryMapperExt userAreaDictionaryMapper;
    @Autowired
    private UserBasicInfoMapperExt userBasicInfoMapperExt;
    @Autowired
    private UserExtInfoMapperExt userExtInfoMapperExt;
    @Autowired
    private UserAccountMapperExt ucAccountMapperExt;
    @Autowired
    private UserStatusService userStatusService;
    @Autowired
    private UserIdentityService userIdentityService;

    @Autowired
    PrivacyMasks privacyMasks;
    @Autowired
    private TbAuthMapperExt tbAuthMapperExt;
    /**
     * 查询用户个人信息
     */
    public UserPersonalDubboInfoDTO userPersonalInfo(String userId) {
        UserPersonalDubboInfoDTO infoDTO = new UserPersonalDubboInfoDTO();
        UserPersonalInfo userPersonalInfo = userPersonalInfoMapper.selectByPrimaryKey(userId);
        if(userPersonalInfo==null){
            return null;
        }

        //查询联系人
        List<UserLinkmanInfo> userLinkmanInfoList = userLinkmanInfoMapperExt.selectByUserId(userId);
        BeanUtils.copyProperties(userPersonalInfo, infoDTO);
        infoDTO.setEducationLevelDesc(UserPersonalEnum.UserEduLevelEnum.getByLevel(infoDTO.getEducationLevel()).getDesc());
        infoDTO.setMaritalStatusDesc(UserPersonalEnum.UserMaritalStatusEnum.getByLevel(infoDTO.getMaritalStatus()).getDesc());

        if (!CollectionUtils.isEmpty(userLinkmanInfoList)) {
            List<LinkManDubboInfoDTO> linkManInfoList = new ArrayList<>();
            for (UserLinkmanInfo userLinkmanInfo : userLinkmanInfoList) {
                LinkManDubboInfoDTO linkManDubboInfoDTO = new LinkManDubboInfoDTO();
                BeanUtils.copyProperties(userLinkmanInfo, linkManDubboInfoDTO);
                linkManDubboInfoDTO.setMobileNo(this.decryptString(userLinkmanInfo.getMobileNo()));
                linkManInfoList.add(linkManDubboInfoDTO);
            }
            infoDTO.setLinkManInfoList(linkManInfoList);
        }
        log.info("userPersonalInfo.userId={},result={}",userId,JSON.toJSONString(infoDTO));
        return infoDTO;
    }

    /**
     * 查询用户职业信息
     */
    public UserProfessionDubboInfoDTO userProfessionInfo(String userId) {
        return Optional.ofNullable(userProfessionInfoMapper.selectByPrimaryKey(userId))
                .map(userProfessionInfo -> {
                    userProfessionInfo.setCompanyPhone(privacyMasks.decryptPrivacy(userProfessionInfo.getCompanyPhone()));
                    UserProfessionDubboInfoDTO result = new UserProfessionDubboInfoDTO();
                    BeanUtils.copyProperties(userProfessionInfo, result);
                    return result;
                }).orElse(null);
    }

    /**
     * 保存用户个人信息与职业信息
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveOrUpdateUserPersonalInfo(UserPersonalDubboInfoDTO userPersonalDubboInfoDTO) {
        //处理用户个人信息
        editUserPersonalInfo(userPersonalDubboInfoDTO);
        //处理联系人信息
        editLinkManInfo(userPersonalDubboInfoDTO);
    }

    /**
     * 修改用户人个信息与职业信息
     */
    @Transactional(rollbackFor = Exception.class)
    public void editUserPersonalInfo(UserPersonalDubboInfoDTO userPersonalDubboInfoDTO) {
        Assert.notNull(userPersonalDubboInfoDTO,"个人信息不能为空");
        String userId = userPersonalDubboInfoDTO.getUserId();
        UserPersonalInfo oldUserPersonalInfo = userPersonalInfoMapper.selectByPrimaryKey(userId);

        // 日期时间
        Date now = new Date();
        UserPersonalInfo newUserPersonalInfo = new UserPersonalInfo();
        BeanUtils.copyProperties(userPersonalDubboInfoDTO, newUserPersonalInfo);

        // 用户个人信息已存在, 则更新用户信息
        if (oldUserPersonalInfo != null) {
            Byte educationAuthStatus = oldUserPersonalInfo.getEducationAuthStatus();
            //如果学历已认证，则不能修改学历信息
            if(UserPersonalEnum.EducationAuthStatusEnum.AUTH.getStatus().byteValue()==educationAuthStatus.byteValue()){
                newUserPersonalInfo.setEducationLevel(oldUserPersonalInfo.getEducationLevel());
                newUserPersonalInfo.setEducationAuthStatus(UserPersonalEnum.EducationAuthStatusEnum.AUTH.getStatus());
            }

            newUserPersonalInfo.setUpdateTime(now);
            userPersonalInfoMapper.updateByPrimaryKeySelective(newUserPersonalInfo);
        } else {// 更新用户信息
            newUserPersonalInfo.setCreateTime(now);
            newUserPersonalInfo.setUpdateTime(now);
            userPersonalInfoMapper.insertSelective(newUserPersonalInfo);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void editLinkManInfo(UserPersonalDubboInfoDTO userPersonalDubboInfoDTO) {
        Assert.notNull(userPersonalDubboInfoDTO,"个人信息不能为空");
        String userId = userPersonalDubboInfoDTO.getUserId();
        List<LinkManDubboInfoDTO> linkManInfoList = userPersonalDubboInfoDTO.getLinkManInfoList();
        if (CollectionUtils.isEmpty(linkManInfoList)) {
            return;
        }
        int len = linkManInfoList.size();
        //int linkManSize = (len<=2?len:2); //限制只接受两个联系人
        for (int i = 0; i < len; i++) {
            LinkManDubboInfoDTO temp = linkManInfoList.get(i);
            // 新增当前用户下联系人
            Long orderNo = i + 1L;
            saveLinkManInfo(userId,orderNo,temp);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void saveLinkManInfo(String userId,Long orderNo,LinkManDubboInfoDTO linkManDubboInfoDTO){
        Date now = new Date();

        UserLinkmanInfo newUserLinkmanInfo = new UserLinkmanInfo();
        BeanUtils.copyProperties(linkManDubboInfoDTO, newUserLinkmanInfo);
        newUserLinkmanInfo.setUserId(userId);
        newUserLinkmanInfo.setMobileNo(this.ecryptString(linkManDubboInfoDTO.getMobileNo()));
        newUserLinkmanInfo.setOrderNo(orderNo);
        newUserLinkmanInfo.setUpdateTime(now);

        UserLinkmanInfo oldUserLinkmanInfo = userLinkmanInfoMapperExt.selectByUserIdAndOrderNo(userId, orderNo);
        if(oldUserLinkmanInfo ==null){
            newUserLinkmanInfo.setId(snowflakeIdWorker.nextId());
            newUserLinkmanInfo.setCreateTime(now);
            userLinkmanInfoMapperExt.insertSelective(newUserLinkmanInfo);
        }else{
            newUserLinkmanInfo.setId(oldUserLinkmanInfo.getId());
            userLinkmanInfoMapperExt.updateByUserIdSelective(newUserLinkmanInfo);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void saveOrUpdateUserProfessionInfo(UserProfessionDubboInfoDTO userProfessionDubboInfoDTO) {
        String userId = userProfessionDubboInfoDTO.getUserId();

        // 日期时间
        Date now = new Date();
        UserProfessionInfo newUserProfessionInfo = new UserProfessionInfo();
        BeanUtils.copyProperties(userProfessionDubboInfoDTO, newUserProfessionInfo);
        newUserProfessionInfo.setCompanyPhone(ecryptString(newUserProfessionInfo.getCompanyPhone()));

        long count = userProfessionInfoMapper.countByUserId(userId);
        if (count > 0) {//存在则更新
            newUserProfessionInfo.setUpdateTime(now);
            userProfessionInfoMapper.updateByPrimaryKeySelective(newUserProfessionInfo);
        } else {
            newUserProfessionInfo.setCreateTime(now);
            userProfessionInfoMapper.insertSelective(newUserProfessionInfo);
        }

        DataStatus dataStatus = new DataStatus();
        dataStatus.setUserId(userId);
        dataStatus.setDataType(UserDataTypeEnum.PERSONAL_INFO.getValue());
        dataStatus.setDataStatus(UserDataStatusEnum.PersonInfoStatus.COMPLETE.getStatus());
        dataStatus.setAuthTime(now);
        dataStatus.setUpdateTime(now);
        userStatusService.saveDataStatusByUserIdAndType(dataStatus);
    }

    /**
     * 根据区域名称查询区域code 模糊匹配  areaName%
     *
     * @param areaName
     * @return
     */
    public String selectAreaCodeByAreaName(String areaName) {
        return userAreaDictionaryMapper.selectAreaCodeByAreaName(areaName);
    }

    /**
     * 根据areaName 查询areaCode与parentCode,结果可能会有多条 如南山区
     *
     * @param areaName
     * @return
     */
    public List<Map<String, String>> selectAreaCodeAndParentCodeByAreaName(String areaName) {
        return userAreaDictionaryMapper.selectAreaCodeAndParentCodeByAreaName(areaName);
    }

    /**
     * 用户信息检查（基本信息、个人信息、职业信息、账户）
     *
     * @param userId
     * @return
     */
    public UserInfoCheckResposeDTO userInfoCheck(String userId) {
        log.info("userInfoCheck.userId={}",userId);

        long basicInfoCount = userBasicInfoMapperExt.countByUserId(userId);
        log.info("userInfoCheck.userId={},basicInfoCount={}",userId,basicInfoCount);
        if (basicInfoCount == 0) {
            return this.getResponseDTO(LoanLimitMessageEnum.LIMIT_10037);
        }

        long personalCount = userPersonalInfoMapper.countByUserId(userId);
        log.info("userInfoCheck.userId={},personalCount={}",userId,personalCount);
        if (personalCount == 0) {
            return this.getResponseDTO(LoanLimitMessageEnum.LIMIT_10038);
        }

        long professionCount = userProfessionInfoMapper.countByUserId(userId);
        log.info("userInfoCheck.userId={},professionCount={}",userId,professionCount);
        if (professionCount == 0) {
            return this.getResponseDTO(LoanLimitMessageEnum.LIMIT_10039);
        }

        long accountCount = ucAccountMapperExt.countByUserId(userId);
        log.info("userInfoCheck.userId={},accountCount={}",userId,accountCount);
        if (accountCount == 0) {
            return this.getResponseDTO(LoanLimitMessageEnum.LIMIT_10040);
        }

        IdentityInfo identityInfo = userIdentityService.getByUserId(userId);
        log.info("userInfoCheck.userId={},identityInfo={}",userId,identityInfo);
        if(identityInfo==null){
            return this.getResponseDTO(LoanLimitMessageEnum.LIMIT_10043);
        }

        UserInfoCheckResposeDTO resposeDTO = new UserInfoCheckResposeDTO();
        resposeDTO.setCheckStatus(LoanLimitMessageEnum.LIMIT_10000.getLimitCode());
        return resposeDTO;
    }

    private UserInfoCheckResposeDTO getResponseDTO(LoanLimitMessageEnum loanLimitMessageEnum){
        UserInfoCheckResposeDTO responseDTO = new UserInfoCheckResposeDTO();
        responseDTO.setCheckStatus(loanLimitMessageEnum.getLimitCode());
        responseDTO.setAlertTitle(loanLimitMessageEnum.getLimitMessageTitle());
        responseDTO.setAlertDesc(loanLimitMessageEnum.getLimitMessageDesc());
        return responseDTO;
    }

    public UserRealNameInfoDTO getUserRealNameInfo(String userId){
        UserRealNameInfo userRealNameInfo= userBasicInfoMapperExt.getUserRealNameInfo(userId);
        if(userRealNameInfo==null){
            return null;
        }
        UserRealNameInfoDTO userRealNameInfoDTO=new UserRealNameInfoDTO();
        BeanUtils.copyProperties(userRealNameInfo, userRealNameInfoDTO);
        return userRealNameInfoDTO;
    }

    /**
     * 检测用户城市是否允许借款
     * @param userId
     * @param allowLoanCity
     * @return
     */
    public boolean checkUserAllowLoanCity(String userId, String allowLoanCity) {
        // 检测身份证地址
        String cityCode = null;
        IdentityInfo identityInfo = userIdentityService.getByUserId(userId);
        if(identityInfo != null) {
            cityCode = identityInfo.getAddressCode().substring(0, 4) + "00"; // 身份证所在城市的编码
            if (!allowLoanCity.contains(cityCode)) {
                return false;
            }
        }
        // 检测居住地址
        UserPersonalInfo userPersonalInfo = userPersonalInfoMapper.selectByPrimaryKey(userId);
        if(userPersonalInfo != null) {
            String livingProvince = userPersonalInfo.getLivingProvince();
            String livingCity = userPersonalInfo.getLivingCity();
            if (livingProvince.contains("北京") || livingProvince.contains("天津") || livingProvince.contains("上海") || livingProvince.contains("重庆") ||
                    livingProvince.contains("香港") || livingProvince.contains("澳门")) {
                cityCode = this.selectAreaCodeByAreaName(livingProvince); //直辖市用省份字段判断
            } else {
                cityCode = this.selectAreaCodeByAreaName(livingCity);
            }
            if (StringUtils.isNotBlank(cityCode) && allowLoanCity.contains(cityCode)) {
                return false;
            }
        }
        // 检测工作地址
        UserProfessionInfo userProfessionInfo = userProfessionInfoMapper.selectByPrimaryKey(userId);
        if(userProfessionInfo != null) {
            String companyProvince = userProfessionInfo.getCompanyProvince();
            String companyCity = userProfessionInfo.getCompanyCity();
            if (companyProvince.contains("北京") || companyProvince.contains("天津") || companyProvince.contains("上海") || companyProvince.contains("重庆") ||
                    companyProvince.contains("香港") || companyProvince.contains("澳门")) {
                cityCode = this.selectAreaCodeByAreaName(companyProvince); //直辖市用省份字段判断
            } else {
                cityCode = this.selectAreaCodeByAreaName(companyCity);
            }
            if (StringUtils.isNotBlank(cityCode) && allowLoanCity.contains(cityCode)) {
                return false;
            }
        }

        return true;
    }

    /**
     * 解密字符串
     *
     * @param str 密文
     */
    private String decryptString(String str) {
        return Optional.ofNullable(str).map(s->privacyMasks.decryptPrivacy(s)).orElse(null);
    }

    /**
     * 加密字符串
     *
     * @param str 明文
     */
    private String ecryptString(String str) {
        return Optional.ofNullable(str).map(s->privacyMasks.encryptPrivacy(s)).orElse(null);
    }

    /**
     * 修改学历信息
     * @param userId
     * @param userEduLevelEnum
     * @param educationAuthStatusEnum
     * @param educationAuthTime
     */
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public void updateEducationInfo(String userId,UserPersonalEnum.UserEduLevelEnum userEduLevelEnum,UserPersonalEnum.EducationAuthStatusEnum educationAuthStatusEnum,Date educationAuthTime){
        userPersonalInfoMapper.updateEducationInfo(userId,userEduLevelEnum,educationAuthStatusEnum,educationAuthTime);
    }

    /**
     * 获取极速借开放城市
     */
    public List<UserAreaDictionary> selectFastBorrowAccreditCity(List<String> areaCode) {

        return userAreaDictionaryMapper.selectFastBorrowAccreditCity(areaCode);
    }

    public String selectAreaNameByAreaCode(String areaCode) {
        return Optional.ofNullable(userAreaDictionaryMapper.selectByPrimaryKey(areaCode))
                .map(areaDict->areaDict.getAreaName()).orElse(null);
    }

    public DripSummaryInfoDTO getMyDripSummaryInfo(String userId) {
        DripSummaryInfoDTO dripSummaryInfoDTO = new DripSummaryInfoDTO();
        UserBasicInfo userBasicInfo = userBasicInfoMapperExt.selectByPrimaryKey(userId);
        if(userBasicInfo != null){
            Long registerDays = DateUtils.daysBetween(userBasicInfo.getCreateTime(),new Date());
            if (registerDays.intValue() == 0){
                dripSummaryInfoDTO.setRegisterDays(Long.valueOf("1")); //当天注册用户，显示1天
            }else{
                dripSummaryInfoDTO.setRegisterDays(registerDays + 1);
            }

        }
        return dripSummaryInfoDTO;
    }

    public LoanConsumeInfoResponseDTO selectLoanConsumeInfo(String borrowUserId){
        LoanConsumeInfoResponseDTO responseDTO = new LoanConsumeInfoResponseDTO();
        TbAuth tbAuth = tbAuthMapperExt.selectByPrimaryKey(borrowUserId);
        if (tbAuth != null){
            int zhimaScore = tbAuth.getZhimaPoint() == null ? 0 : tbAuth.getZhimaPoint();//芝麻分
            int taoqiValue = tbAuth.getVipCount() == null ? 0 : tbAuth.getVipCount();
            int yearVolume = tbAuth.getYearPaySum() == null ? 0 : tbAuth.getYearPaySum().intValue();
            responseDTO.setZhimaScore(this.praseConsumeInfo(zhimaScore,100,Byte.valueOf("0")));
            responseDTO.setTaoqiValue(this.praseConsumeInfo(taoqiValue,200,Byte.valueOf("0")));
            responseDTO.setYearVolume(this.praseConsumeInfo(yearVolume,5000,Byte.valueOf("1")));
        }else{
            responseDTO.setZhimaScore("0-100");
            responseDTO.setTaoqiValue("0-200");
            responseDTO.setYearVolume("0-5千元");
        }

        return responseDTO;
    }

    private String praseConsumeInfo(int amount, int sectionValue,Byte type){
        String result = "";
        int max = amount % sectionValue == 0 ? amount / sectionValue : (amount / sectionValue) + 1;
        int maxSectionVal = max == 0 ? (max + 1) * sectionValue : max * sectionValue;
        int minSectionVal = max == 0 ? 0 : (max - 1) * sectionValue + 1;
        if (type.equals(Byte.valueOf("0"))) {
            if (minSectionVal > 1){
                result = minSectionVal+"-"+maxSectionVal;
            }else{
                result = "0-"+sectionValue;
            }

        }else {
            int section = 10000;
            int minValue = minSectionVal / section;
            int maxValue = maxSectionVal / section;
            int maxRemainder = maxSectionVal%section;
            if(maxValue == 0){
                result = "0-5千元";
            }else if(maxRemainder == 0 && maxValue == 1){
                result = "5千-1万元";
            }else if(maxRemainder == 0 && maxValue > 1){
                result = minValue+"万5千-"+maxValue+"万元";
            }else if(maxRemainder != 0 && maxValue > 0){
                result = minValue+"万-"+maxValue+"万5千元";
            }
        }
        return result;
    }

	public List<QueryBorrowerUserResponseDTO> queryBorrowerUserListByLinkManPhoneNum(
			QueryBorrowerUserRequestDTO reqDTO) {
		String mobileNo = reqDTO.getMobileNo();
		return userLinkmanInfoMapperExt.queryBorrowerUserListByLinkManPhoneNum(mobileNo);
	}
	
}
